Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

feat(dm-result): record outbox audit on REST-fallback DM delivery (Phase 5.18) - #86

Merged
jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.18-dm-result-outbox
Jun 2, 2026
Merged

jgluck96 merged 1 commit into
dev-clientfrom
josh/phase-5.18-dm-result-outbox

Conversation

@jgluck96

@jgluck96 jgluck96 commented Jun 2, 2026

Copy link
Copy Markdown

Summary

Closes the last bridge-family outbox coverage gap. Phase 5.16 added outbox_log.append calls to discord-bridge.py for live-bridge deliveries; this phase ports the OSS dm-result.py write site for the REST-fallback path used when the live bridge isn't connected.

Without this PR, an offline-bridge owner DM would land successfully on Discord but never appear in the dashboard's Outbox card alongside live-bridge rows — silently missing every delivery during bridge downtime.

Changes

src/dm-result.py — after the success-state print "sent to DM" and before the final return True in send_dm, append an outbox audit row wrapped in try / import outbox_log / append / except Exception: pass.

Two intentional design points:

Field Value Rationale
channel_type "discord_dm" Matches discord-bridge.py's live-bridge vocabulary so both surfaces render the same 💬 icon in the dashboard card
recipient_label "owner DM (via dm-result.py)" (constant) Deliberate divergence from discord-bridge's per-user label ("alice DM"). dm-result doesn't have the username locally and we don't want to pay an extra REST call just to populate it. The constant marker doubles as an audit-trail signal that lets operators distinguish REST-fallback rows from live-bridge rows at a glance

Tests

tests/dm-result-outbox.test.py (new, 6 cases)

  • Structural: exactly 1 append site, fail-open wrapped.
  • Channel-type vocabulary: must be discord_dm (matches discord-bridge writes for icon parity).
  • Variable-binding: required kwargs present.
  • Recipient-label marker: must be the dm-result audit marker so operators can distinguish surfaces.
  • Positioning: append sits AFTER the "sent to DM" success print and BEFORE the final return True. Catches both a refactor that hoists it above an error branch (would record rows for unsent messages) and one that moves it past the return (unreachable).
  • Round-trip: append → outbox_log → dashboard.get_outbox reader picks it up with the right channel_type + marker.

Test plan

  • python3 tests/dm-result-outbox.test.py → 6/6
  • Full Python regression sweep → 60/60 pass (was 59; +1 net-new file)
  • pnpm -s typecheck → clean
  • python3 -m py_compile src/dm-result.py → clean

Result

Bridge → outbox → dashboard pipeline is now feature-complete across:

Surface Writer Phase
slack slack-bridge.py (pre-existing)
discord (live bridge) discord-bridge.py 5.16
discord (REST fallback) dm-result.py 5.18 (this PR)
telegram telegram-bridge.py 5.17

Roadmap

The outbox pipeline is now complete. Possible next directions if you want to keep going on Phase 5:

  • Phase 5.19 candidate: audit remaining dashboard.py divergence (we touched it for the reader in 5.15; other 100+ lines of diff are deliberate path-resolution divergence — confirm there's no hidden portable win we missed).
  • Phase 5.20 candidate: scan the morning-briefing.py / obsidian-mirror.py / task_archive.py / result_channel_key.py OSS-only files for any that have a clear, low-risk, additive port path.

Or this may be a natural stopping point for the OSS → private sync.

Made with Cursor

…ase 5.18)

Closes the bridge-family outbox coverage gap. Phase 5.16 added
outbox_log.append calls to discord-bridge.py for live-bridge deliveries;
this phase ports the OSS dm-result.py write site for the REST-fallback
path used when the live bridge isn't connected. Without this PR, an
offline-bridge owner DM would land successfully on Discord but never
appear in the dashboard's Outbox card alongside live-bridge rows —
silently missing every delivery during bridge downtime.

Changes:
- `src/dm-result.py`: after the success-state print "sent to DM"
  and before the final `return True` in `send_dm`, append an outbox
  audit row wrapped in `try / import outbox_log / append / except
  Exception: pass`. channel_type="discord_dm" matches discord-bridge's
  live-bridge vocabulary so both surfaces render the same 💬 icon in
  the dashboard card. recipient_label is the constant
  "owner DM (via dm-result.py)" — a deliberate divergence from
  discord-bridge's per-user label, used as an audit-trail marker
  letting operators distinguish REST-fallback rows from live-bridge
  rows at a glance.

- `tests/dm-result-outbox.test.py` (new, 6 tests):
  - Structural: exactly 1 append site, fail-open wrapped.
  - Channel-type vocabulary: must be `discord_dm` (matches discord-
    bridge writes so both surfaces share the same icon).
  - Variable-binding: required kwargs present (channel_type, recipient,
    body, recipient_label).
  - Recipient-label marker: must be the dm-result audit marker so
    operators can distinguish surfaces.
  - Positioning: append sits AFTER the "sent to DM" success print
    and BEFORE the final `return True` (catches a refactor that
    hoists it above an error branch — would record rows for unsent
    messages — or moves it past the return — unreachable).
  - Round-trip: append → outbox_log → dashboard.get_outbox reader
    picks it up with the right channel_type + marker.

Verification:
- 60/60 Python tests pass (was 59; +1 net-new file).
- TypeScript typecheck clean.
- `python3 -m py_compile src/dm-result.py` clean.

Phase 5.18 of the OSS → private sync. Bridge → outbox → dashboard
pipeline is now feature-complete across slack + discord (live bridge +
REST fallback) + telegram.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant